﻿#region Disclaimer/Info

/////////////////////////////////////////////////////////////////////////////////////////////////
//
//   File:		RoutingService.cs
//   Website:		http://dexterblogengine.com/
//   Authors:		http://dexterblogengine.com/About.ashx
//   Rev:		1
//   Created:		19/01/2011
//   Last edit:		19/01/2011
//   License:		GNU Library General Public License (LGPL)
// 
//   For updated news and information please visit http://dexterblogengine.com/
//   Dexter is hosted to Codeplex at http://dexterblogengine.codeplex.com
//   For any question contact info@dexterblogengine.com
//
///////////////////////////////////////////////////////////////////////////////////////////////////

#endregion

using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
using System.Web.Routing;
using Dexter.Logger.Contracts;
using Dexter.Services;
using Dexter.Web.Mvc.Routing.Routehandlers;
using Dexter.Web.Mvc.Routing.Routes;
using Dexter.Web.Routing;

namespace Dexter.Web.Mvc.Routing {
	public class RoutingService : IRoutingService {
		readonly ILogger logger;
		readonly IPageService pageService;
		readonly RouteCollection routes;
		readonly ISetupService setupService;
		readonly ILegacyUrlService legacyUrlService;
		const string MATCH_POSITIVE_INTEGER = @"\d{1,10}";

		/// <summary>
		/// Initializes a new instance of the <see cref="RoutingService"/> class.
		/// </summary>
		/// <param name="logger">The logger.</param>
		/// <param name="pageService">The page service.</param>
		/// <param name="setupService">The setup service.</param>
		public RoutingService ( ILogger logger , IPageService pageService , ISetupService setupService, ILegacyUrlService legacyUrlService) {
			this.logger = logger;
			this.pageService = pageService;
			this.setupService = setupService;
			this.legacyUrlService = legacyUrlService;
			routes = RouteTable.Routes;
		}

		#region Implementation of IRoutingService

		/// <summary>
		/// 	Updates the routes.
		/// </summary>
		public void UpdateRoutes ( ) {
			RegisterRoutes ( );
		}

		/// <summary>
		/// 	Registers all mvc routes.
		/// </summary>
		public void RegisterRoutes ( ) {
			routes.Clear ( );
			
			AreaRegistration.RegisterAllAreas ( );

			if (!setupService.IsInstalled) {
				routes.Add ( new SetupRoute ( ) );
				return;
			}

			routes.IgnoreRoute ( "{resource}.axd/{*pathInfo}" );
			routes.IgnoreRoute ( "{*allaspx}" , new {allaspx = @".*\.aspx(/.*)?"} );
			routes.IgnoreRoute ( "{*favicon}" , new {favicon = @"(.*/)?favicon.ico(/.*)?"} );
			routes.IgnoreRoute ( "robots.txt" );
			routes.IgnoreRoute ( "wlwmanifest.xml" );
			routes.IgnoreRoute ( "Glimpse/Config/" );

			var legacyUrl = legacyUrlService.GetListPaged(0, 500, false);

			legacyUrl.Result.ForEach(x =>
			{
				logger.DebugFormat("Registering route for legacy url '{0}'", x);
				routes.MapRoute(string.Concat("Redirect_", x.SourceUrl),
								  x.SourceUrl,
								  new
								  {
									  controller = "Redirect",
									  action = "Index",
									  id = (int)x.Redirect,
									  url = x.TargetUrl
								  }, new string[] { "Dexter.Web.Mvc.Controllers.FrontEnd" });

				logger.DebugFormat("Registered route for legacy url '{0}'", x);
			});

			IEnumerable <string> slugs = pageService.GetAllSlugs ( );

			slugs.ForEach ( x => {
			                	logger.DebugFormat ( "Registering route for dynamic page '{0}'" , x );
			                	routes.MapRoute ( string.Concat("Page_",x) ,
			                	                  x ,
			                	                  new {
			                	                  	controller = "Page" ,
			                	                  	action = "Index" ,
			                	                  	id = x
			                	                  } , new string[] {"Dexter.Web.Mvc.Controllers.FrontEnd"} );
			                	logger.DebugFormat ( "Registered route for dynamic page '{0}'" , x );
			                } );

			routes.MapRoute ( "Images" , "Images/{*id}" , new {
				controller = "Home" ,
				action = "GetMediaResource" ,
				id = UrlParameter.Optional } , 
				new string[] {"Dexter.Web.Mvc.Controllers.FrontEnd"} );

			routes.MapRoute ( "Media" , "Media/{*id}" , new {
				controller = "Home" ,
				action = "GetMediaResource" ,
				id = UrlParameter.Optional } ,  
				new string[] {"Dexter.Web.Mvc.Controllers.FrontEnd"} );

			routes.MapRoute ( "Contents" , "Contents/{*id}" , new {
				controller = "Home" ,
				action = "GetMediaResource" ,
				id = UrlParameter.Optional } , 
				new string[] {"Dexter.Web.Mvc.Controllers.FrontEnd"} );

			routes.MapRoute ( "Scripts" , "Scripts/{*id}" , new {
				controller = "Home" ,
				action = "GetMediaResource" ,
				id = UrlParameter.Optional } , 
				new string[] {"Dexter.Web.Mvc.Controllers.FrontEnd"} );

			routes.MapRoute ( "Styles" , "Styles/{*id}" , new {
				controller = "Home" ,
				action = "GetMediaResource" ,
				id = UrlParameter.Optional } , 
				new string[] {"Dexter.Web.Mvc.Controllers.FrontEnd"} );

			routes.MapRoute ( "SubTextUrls", "archive/{year}/{month}/{day}/{id}.aspx", new {
				controller = "Blog",
				action = "Post",
				id = string.Empty } , 
				new string[] {"Dexter.Web.Mvc.Controllers.FrontEnd"} );

			routes.MapRoute (
				"Default" ,
				"{controller}/{action}/{id}" ,
				new {controller = "Home" , action = "Index" , id = UrlParameter.Optional} ,
				new string[] {"Dexter.Web.Mvc.Controllers.FrontEnd"}
				);

			routes.MapRoute (
				"Home" ,
				"{controller}/{action}/Page/{page}" ,
				new {controller = "Home" , action = "Index" , id = UrlParameter.Optional , page = 1} ,
				new string[] {"Dexter.Web.Mvc.Controllers.FrontEnd"}
				);

			routes.MapRoute (
				"DefaultWithPaging" ,
				"{controller}/{action}/{id}/Page/{page}" ,
				new {controller = "Blog" , action = "Index" , id = UrlParameter.Optional , page = 1} ,
				new string[] {"Dexter.Web.Mvc.Controllers.FrontEnd"}
				);

			routes.MapRoute (
				"ArchivesPaged" ,
				"{controller}/{action}/{year}/{month}/Page/{page}" ,
				new { controller = "Archives", action = "Posts", year = MATCH_POSITIVE_INTEGER, month = MATCH_POSITIVE_INTEGER, page = MATCH_POSITIVE_INTEGER },
				new string[] {"Dexter.Web.Mvc.Controllers.FrontEnd"}
				);

			routes.MapRoute (
				"Archives" ,
				"{controller}/{action}/{year}/{month}" ,
				new { controller = "Archives", action = "Posts", year = MATCH_POSITIVE_INTEGER, month = MATCH_POSITIVE_INTEGER },
				new string[] {"Dexter.Web.Mvc.Controllers.FrontEnd"}
				);

			routes.MapRoute (
				"PostDetail" ,
				"{controller}/{action}/{year}/{month}/{day}/{id}" ,
				new {controller = "Blog" , action = "Post" , id = UrlParameter.Optional} ,
				new string[] {"Dexter.Web.Mvc.Controllers.FrontEnd"}
				);

			// route that simulates the custom wordpress permalink (day and name route)
			routes.MapRoute (
				"WordPressDayAndName" ,
				"index.php/{year}/{month}/{day}/{id}" ,
				new {controller = "Blog" , action = "Post"} ,
				new string[] {"Dexter.Web.Mvc.Controllers.FrontEnd"} );

			// route that simulates the custom wordpress permalink (month and name route)
			routes.MapRoute ( 
				"WordPressMonthAndName" , 
				"index.php/{year}/{month}/{id}" , 
				new { controller = "Blog" , action = "Post", id = string.Empty }, 
				new string[] { "Dexter.Web.Mvc.Controllers.FrontEnd" } );

			// route that simulates the custom wordpress permalink (month and name route)
			routes.MapRoute ( 
				"Dexterv2", 
				"blog/post/{id}", 
				new { controller = "Blog", action = "Post" }, 
				new string[] { "Dexter.Web.Mvc.Controllers.FrontEnd" } );

			routes.MapRoute ( "Errors" , "{*url}" , new {
				controller = "Errors" ,
				action = "NotFound"
			} );
		}

		#endregion
	}
}